library(nflfastR)
library(espnscrapeR)
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.0 ──
## ✓ ggplot2 3.3.2     ✓ purrr   0.3.4
## ✓ tibble  3.0.4     ✓ dplyr   1.0.2
## ✓ tidyr   1.1.2     ✓ stringr 1.4.0
## ✓ readr   1.4.0     ✓ forcats 0.5.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(xlsx)
library(ggplot2)
library(dplyr)
library(ggimage)
library(ggthemes)
library(scales)
## 
## Attaching package: 'scales'
## The following object is masked from 'package:purrr':
## 
##     discard
## The following object is masked from 'package:readr':
## 
##     col_factor
library(furrr)
## Loading required package: future
library(gt)
library(DT)

Load play by play data

#Takes about 45 seconds
seasons <- 1999:2020
pbp <- map_df(seasons, function(x) {
  readRDS(url(paste0("https://raw.githubusercontent.com/guga31bb/nflfastR-data/master/data/play_by_play_",x,".rds")))
})

Load QBR data

scrapeQBRData <- function(startyr, endyr, startwk, endwk) {
  master <- data.frame()
  for (i in endyr:startyr) {
    season <- data.frame()
    for (j in endwk:startwk) {
      week <- get_nfl_qbr(week = j, season = i)
      season <- rbind(week, season)
    }
    master <- rbind(master, season)
  }
  return(master)
}

scrapeQBRSeasonData <- function(startyr, endyr) {
  master <- data.frame()
  for (i in endyr:startyr) {
    season <- get_nfl_qbr(season = i)
    master <- rbind(master, season)
    }
  return(master)
}
  
qbr_by_season <- scrapeQBRSeasonData(2006, 2020)
## Scraping QBR totals for 2020!
## Scraping QBR totals for 2019!
## Scraping QBR totals for 2018!
## Scraping QBR totals for 2017!
## Scraping QBR totals for 2016!
## Scraping QBR totals for 2015!
## Scraping QBR totals for 2014!
## Scraping QBR totals for 2013!
## Scraping QBR totals for 2012!
## Scraping QBR totals for 2011!
## Scraping QBR totals for 2010!
## Scraping QBR totals for 2009!
## Scraping QBR totals for 2008!
## Scraping QBR totals for 2007!
## Scraping QBR totals for 2006!
qbr06to19 <- scrapeQBRData(2006, 2019, 1, 17)
## Scraping weekly QBR for week 17 of 2019!
## Scraping weekly QBR for week 16 of 2019!
## Scraping weekly QBR for week 15 of 2019!
## Scraping weekly QBR for week 14 of 2019!
## Scraping weekly QBR for week 13 of 2019!
## Scraping weekly QBR for week 12 of 2019!
## Scraping weekly QBR for week 11 of 2019!
## Scraping weekly QBR for week 10 of 2019!
## Scraping weekly QBR for week 9 of 2019!
## Scraping weekly QBR for week 8 of 2019!
## Scraping weekly QBR for week 7 of 2019!
## Scraping weekly QBR for week 6 of 2019!
## Scraping weekly QBR for week 5 of 2019!
## Scraping weekly QBR for week 4 of 2019!
## Scraping weekly QBR for week 3 of 2019!
## Scraping weekly QBR for week 2 of 2019!
## Scraping weekly QBR for week 1 of 2019!
## Scraping weekly QBR for week 17 of 2018!
## Scraping weekly QBR for week 16 of 2018!
## Scraping weekly QBR for week 15 of 2018!
## Scraping weekly QBR for week 14 of 2018!
## Scraping weekly QBR for week 13 of 2018!
## Scraping weekly QBR for week 12 of 2018!
## Scraping weekly QBR for week 11 of 2018!
## Scraping weekly QBR for week 10 of 2018!
## Scraping weekly QBR for week 9 of 2018!
## Scraping weekly QBR for week 8 of 2018!
## Scraping weekly QBR for week 7 of 2018!
## Scraping weekly QBR for week 6 of 2018!
## Scraping weekly QBR for week 5 of 2018!
## Scraping weekly QBR for week 4 of 2018!
## Scraping weekly QBR for week 3 of 2018!
## Scraping weekly QBR for week 2 of 2018!
## Scraping weekly QBR for week 1 of 2018!
## Scraping weekly QBR for week 17 of 2017!
## Scraping weekly QBR for week 16 of 2017!
## Scraping weekly QBR for week 15 of 2017!
## Scraping weekly QBR for week 14 of 2017!
## Scraping weekly QBR for week 13 of 2017!
## Scraping weekly QBR for week 12 of 2017!
## Scraping weekly QBR for week 11 of 2017!
## Scraping weekly QBR for week 10 of 2017!
## Scraping weekly QBR for week 9 of 2017!
## Scraping weekly QBR for week 8 of 2017!
## Scraping weekly QBR for week 7 of 2017!
## Scraping weekly QBR for week 6 of 2017!
## Scraping weekly QBR for week 5 of 2017!
## Scraping weekly QBR for week 4 of 2017!
## Scraping weekly QBR for week 3 of 2017!
## Scraping weekly QBR for week 2 of 2017!
## Scraping weekly QBR for week 1 of 2017!
## Scraping weekly QBR for week 17 of 2016!
## Scraping weekly QBR for week 16 of 2016!
## Scraping weekly QBR for week 15 of 2016!
## Scraping weekly QBR for week 14 of 2016!
## Scraping weekly QBR for week 13 of 2016!
## Scraping weekly QBR for week 12 of 2016!
## Scraping weekly QBR for week 11 of 2016!
## Scraping weekly QBR for week 10 of 2016!
## Scraping weekly QBR for week 9 of 2016!
## Scraping weekly QBR for week 8 of 2016!
## Scraping weekly QBR for week 7 of 2016!
## Scraping weekly QBR for week 6 of 2016!
## Scraping weekly QBR for week 5 of 2016!
## Scraping weekly QBR for week 4 of 2016!
## Scraping weekly QBR for week 3 of 2016!
## Scraping weekly QBR for week 2 of 2016!
## Scraping weekly QBR for week 1 of 2016!
## Scraping weekly QBR for week 17 of 2015!
## Scraping weekly QBR for week 16 of 2015!
## Scraping weekly QBR for week 15 of 2015!
## Scraping weekly QBR for week 14 of 2015!
## Scraping weekly QBR for week 13 of 2015!
## Scraping weekly QBR for week 12 of 2015!
## Scraping weekly QBR for week 11 of 2015!
## Scraping weekly QBR for week 10 of 2015!
## Scraping weekly QBR for week 9 of 2015!
## Scraping weekly QBR for week 8 of 2015!
## Scraping weekly QBR for week 7 of 2015!
## Scraping weekly QBR for week 6 of 2015!
## Scraping weekly QBR for week 5 of 2015!
## Scraping weekly QBR for week 4 of 2015!
## Scraping weekly QBR for week 3 of 2015!
## Scraping weekly QBR for week 2 of 2015!
## Scraping weekly QBR for week 1 of 2015!
## Scraping weekly QBR for week 17 of 2014!
## Scraping weekly QBR for week 16 of 2014!
## Scraping weekly QBR for week 15 of 2014!
## Scraping weekly QBR for week 14 of 2014!
## Scraping weekly QBR for week 13 of 2014!
## Scraping weekly QBR for week 12 of 2014!
## Scraping weekly QBR for week 11 of 2014!
## Scraping weekly QBR for week 10 of 2014!
## Scraping weekly QBR for week 9 of 2014!
## Scraping weekly QBR for week 8 of 2014!
## Scraping weekly QBR for week 7 of 2014!
## Scraping weekly QBR for week 6 of 2014!
## Scraping weekly QBR for week 5 of 2014!
## Scraping weekly QBR for week 4 of 2014!
## Scraping weekly QBR for week 3 of 2014!
## Scraping weekly QBR for week 2 of 2014!
## Scraping weekly QBR for week 1 of 2014!
## Scraping weekly QBR for week 17 of 2013!
## Scraping weekly QBR for week 16 of 2013!
## Scraping weekly QBR for week 15 of 2013!
## Scraping weekly QBR for week 14 of 2013!
## Scraping weekly QBR for week 13 of 2013!
## Scraping weekly QBR for week 12 of 2013!
## Scraping weekly QBR for week 11 of 2013!
## Scraping weekly QBR for week 10 of 2013!
## Scraping weekly QBR for week 9 of 2013!
## Scraping weekly QBR for week 8 of 2013!
## Scraping weekly QBR for week 7 of 2013!
## Scraping weekly QBR for week 6 of 2013!
## Scraping weekly QBR for week 5 of 2013!
## Scraping weekly QBR for week 4 of 2013!
## Scraping weekly QBR for week 3 of 2013!
## Scraping weekly QBR for week 2 of 2013!
## Scraping weekly QBR for week 1 of 2013!
## Scraping weekly QBR for week 17 of 2012!
## Scraping weekly QBR for week 16 of 2012!
## Scraping weekly QBR for week 15 of 2012!
## Scraping weekly QBR for week 14 of 2012!
## Scraping weekly QBR for week 13 of 2012!
## Scraping weekly QBR for week 12 of 2012!
## Scraping weekly QBR for week 11 of 2012!
## Scraping weekly QBR for week 10 of 2012!
## Scraping weekly QBR for week 9 of 2012!
## Scraping weekly QBR for week 8 of 2012!
## Scraping weekly QBR for week 7 of 2012!
## Scraping weekly QBR for week 6 of 2012!
## Scraping weekly QBR for week 5 of 2012!
## Scraping weekly QBR for week 4 of 2012!
## Scraping weekly QBR for week 3 of 2012!
## Scraping weekly QBR for week 2 of 2012!
## Scraping weekly QBR for week 1 of 2012!
## Scraping weekly QBR for week 17 of 2011!
## Scraping weekly QBR for week 16 of 2011!
## Scraping weekly QBR for week 15 of 2011!
## Scraping weekly QBR for week 14 of 2011!
## Scraping weekly QBR for week 13 of 2011!
## Scraping weekly QBR for week 12 of 2011!
## Scraping weekly QBR for week 11 of 2011!
## Scraping weekly QBR for week 10 of 2011!
## Scraping weekly QBR for week 9 of 2011!
## Scraping weekly QBR for week 8 of 2011!
## Scraping weekly QBR for week 7 of 2011!
## Scraping weekly QBR for week 6 of 2011!
## Scraping weekly QBR for week 5 of 2011!
## Scraping weekly QBR for week 4 of 2011!
## Scraping weekly QBR for week 3 of 2011!
## Scraping weekly QBR for week 2 of 2011!
## Scraping weekly QBR for week 1 of 2011!
## Scraping weekly QBR for week 17 of 2010!
## Scraping weekly QBR for week 16 of 2010!
## Scraping weekly QBR for week 15 of 2010!
## Scraping weekly QBR for week 14 of 2010!
## Scraping weekly QBR for week 13 of 2010!
## Scraping weekly QBR for week 12 of 2010!
## Scraping weekly QBR for week 11 of 2010!
## Scraping weekly QBR for week 10 of 2010!
## Scraping weekly QBR for week 9 of 2010!
## Scraping weekly QBR for week 8 of 2010!
## Scraping weekly QBR for week 7 of 2010!
## Scraping weekly QBR for week 6 of 2010!
## Scraping weekly QBR for week 5 of 2010!
## Scraping weekly QBR for week 4 of 2010!
## Scraping weekly QBR for week 3 of 2010!
## Scraping weekly QBR for week 2 of 2010!
## Scraping weekly QBR for week 1 of 2010!
## Scraping weekly QBR for week 17 of 2009!
## Scraping weekly QBR for week 16 of 2009!
## Scraping weekly QBR for week 15 of 2009!
## Scraping weekly QBR for week 14 of 2009!
## Scraping weekly QBR for week 13 of 2009!
## Scraping weekly QBR for week 12 of 2009!
## Scraping weekly QBR for week 11 of 2009!
## Scraping weekly QBR for week 10 of 2009!
## Scraping weekly QBR for week 9 of 2009!
## Scraping weekly QBR for week 8 of 2009!
## Scraping weekly QBR for week 7 of 2009!
## Scraping weekly QBR for week 6 of 2009!
## Scraping weekly QBR for week 5 of 2009!
## Scraping weekly QBR for week 4 of 2009!
## Scraping weekly QBR for week 3 of 2009!
## Scraping weekly QBR for week 2 of 2009!
## Scraping weekly QBR for week 1 of 2009!
## Scraping weekly QBR for week 17 of 2008!
## Scraping weekly QBR for week 16 of 2008!
## Scraping weekly QBR for week 15 of 2008!
## Scraping weekly QBR for week 14 of 2008!
## Scraping weekly QBR for week 13 of 2008!
## Scraping weekly QBR for week 12 of 2008!
## Scraping weekly QBR for week 11 of 2008!
## Scraping weekly QBR for week 10 of 2008!
## Scraping weekly QBR for week 9 of 2008!
## Scraping weekly QBR for week 8 of 2008!
## Scraping weekly QBR for week 7 of 2008!
## Scraping weekly QBR for week 6 of 2008!
## Scraping weekly QBR for week 5 of 2008!
## Scraping weekly QBR for week 4 of 2008!
## Scraping weekly QBR for week 3 of 2008!
## Scraping weekly QBR for week 2 of 2008!
## Scraping weekly QBR for week 1 of 2008!
## Scraping weekly QBR for week 17 of 2007!
## Scraping weekly QBR for week 16 of 2007!
## Scraping weekly QBR for week 15 of 2007!
## Scraping weekly QBR for week 14 of 2007!
## Scraping weekly QBR for week 13 of 2007!
## Scraping weekly QBR for week 12 of 2007!
## Scraping weekly QBR for week 11 of 2007!
## Scraping weekly QBR for week 10 of 2007!
## Scraping weekly QBR for week 9 of 2007!
## Scraping weekly QBR for week 8 of 2007!
## Scraping weekly QBR for week 7 of 2007!
## Scraping weekly QBR for week 6 of 2007!
## Scraping weekly QBR for week 5 of 2007!
## Scraping weekly QBR for week 4 of 2007!
## Scraping weekly QBR for week 3 of 2007!
## Scraping weekly QBR for week 2 of 2007!
## Scraping weekly QBR for week 1 of 2007!
## Scraping weekly QBR for week 17 of 2006!
## Scraping weekly QBR for week 16 of 2006!
## Scraping weekly QBR for week 15 of 2006!
## Scraping weekly QBR for week 14 of 2006!
## Scraping weekly QBR for week 13 of 2006!
## Scraping weekly QBR for week 12 of 2006!
## Scraping weekly QBR for week 11 of 2006!
## Scraping weekly QBR for week 10 of 2006!
## Scraping weekly QBR for week 9 of 2006!
## Scraping weekly QBR for week 8 of 2006!
## Scraping weekly QBR for week 7 of 2006!
## Scraping weekly QBR for week 6 of 2006!
## Scraping weekly QBR for week 5 of 2006!
## Scraping weekly QBR for week 4 of 2006!
## Scraping weekly QBR for week 3 of 2006!
## Scraping weekly QBR for week 2 of 2006!
## Scraping weekly QBR for week 1 of 2006!
qbr20 <- scrapeQBRData(2020, 2020, 1, 14)
## Scraping weekly QBR for week 14 of 2020!
## Scraping weekly QBR for week 13 of 2020!
## Scraping weekly QBR for week 12 of 2020!
## Scraping weekly QBR for week 11 of 2020!
## Scraping weekly QBR for week 10 of 2020!
## Scraping weekly QBR for week 9 of 2020!
## Scraping weekly QBR for week 8 of 2020!
## Scraping weekly QBR for week 7 of 2020!
## Scraping weekly QBR for week 6 of 2020!
## Scraping weekly QBR for week 5 of 2020!
## Scraping weekly QBR for week 4 of 2020!
## Scraping weekly QBR for week 3 of 2020!
## Scraping weekly QBR for week 2 of 2020!
## Scraping weekly QBR for week 1 of 2020!
qbr_by_game <- rbind(qbr20, qbr06to19)
qbr_by_game$game_week <- as.numeric(qbr_by_game$game_week)

Cam Newton QBR by season compared to league average and Tom Brady.

avg_qbr <- mean(qbr_by_game$qbr_total)

qbr_by_season %>% 
  filter(name %in% c('Tom Brady', 'Cam Newton')) %>%
  ggplot(aes(x = season, y = qbr_total, color = name)) +
  geom_line(size = 1) +
  geom_hline(yintercept = avg_qbr, color = "black", linetype = "dashed") +
  geom_point(alpha=.7) +
  theme_fivethirtyeight() +
  theme(
    legend.title = element_blank(),
    strip.text = element_text(face = "bold"),
    axis.title.y = element_text(),
    axis.title.x = element_blank()
    ) +
  labs(
    y = "Total QBR",
    title = "Quarterback rating by season",
    subtitle = "Dotted line represents league average from 2006 to 2020",
    caption = "Data: @espnscrapeR | Plot: @LauraStickells"
  ) +
  scale_x_continuous(breaks = seq(min(qbr_by_season$season), max(qbr_by_season$season), by = 1))

Percent QB rushes for Newton and Brady by season.

pats_qb_graph <- pbp %>%
  filter(epa != 0, passer %in% c('T.Brady','C.Newton') | rusher %in% c('T.Brady', 'C.Newton')) %>%
  select(posteam, desc, play_type, qb_scramble, pass, rush, season, passer, rusher) %>%
  mutate(
    player = case_when(
      !is.na(passer) ~ passer,
      !is.na(rusher) ~ rusher
    ) 
  ) %>%
  group_by(season, player) %>%
  summarise(
    run_pct = sum(rush)/n(),
    pass_pct = sum(pass)/n(),
    n = n()
  ) %>%
  ggplot(aes(x = season, y = run_pct, color = player)) +
  geom_line(size = 1) +
  geom_point(alpha=.7) +
  theme_fivethirtyeight() +
  theme(
    legend.title = element_blank(),
    strip.text = element_text(face = "bold"),
    axis.title.y = element_text(),
    axis.title.x = element_blank(),
    axis.text.x = element_text(angle = 30)
    ) +
  labs(
    y = "Run Percentage",
    title = "Quarterback Run Percentage by Season",
    subtitle = "Does not include scrambles",
    caption = "Data: @nflfastR | Plot: @LauraStickells"
  ) +
  scale_x_continuous(breaks = seq(min(pbp$season), max(pbp$season), by = 1)) +
  scale_y_continuous(labels = label_percent(accuracy = 1))
## `summarise()` regrouping output by 'season' (override with `.groups` argument)
pats_qb_graph

Plotly comparing percent of quarterback runs and QBR by week.

library(plotly)
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
pbp_name_fix <- pbp
### Don't run the lines below twice
pbp_name_fix$passer <- trimws(gsub(".", ". ", pbp_name_fix$passer, fixed = TRUE))
pbp_name_fix$rusher <- trimws(gsub(".", ". ", pbp_name_fix$rusher, fixed = TRUE))

significant_qbs <- c('C. Newton', 'D. Jones', 'K. Murray', 'L. Jackson')

significant_pbp <- pbp_name_fix %>%
  filter(epa != 0, passer %in% significant_qbs | rusher %in% significant_qbs) %>%
  select(posteam, desc, play_type, qb_scramble, pass, rush, season, passer, rusher, week, away_score, away_team, home_score, home_team) %>%
  mutate(
    player = case_when(
      !is.na(passer) ~ passer,
      !is.na(rusher) ~ rusher
    ) 
  ) %>%
  group_by(week, season, player, away_score, away_team, home_score, home_team) %>%
  summarise(
    run_pct = sum(rush)/n(),
    pass_pct = sum(pass)/n(),
    n = n()
  )
## `summarise()` regrouping output by 'week', 'season', 'player', 'away_score', 'away_team', 'home_score' (override with `.groups` argument)
significant_qbrs <- qbr_by_game %>%
  filter(short_name %in% significant_qbs)

data <- left_join(significant_pbp, significant_qbrs, by = c("player" = "short_name", "week" = "game_week", "season" = "season"))
write.csv(data, 'data.csv')
  
graph <- data %>%
  filter(season == 2020, player == 'C. Newton') %>%
  ggplot(aes(x = week, y = run_pct)) +
  geom_line(size = 1, color = "gray") +
  geom_point(aes(color = qbr_total, text= paste(away_team, away_score, " - ", home_team, home_score, "<br>", "QBR: ", qbr_total, "<br>", "Run: ", run_pct)), alpha=.7, size = 3) +
   scale_colour_gradient(low = "gold", high = "green4", name = "QBR") +
  theme(
    strip.text = element_text(face = "bold"),
    axis.title.y = element_text(),
    axis.title.x = element_text(),
    ) +
  labs(
    y = "Percent Runs",
    x = "Week",
    title = "Percent of quarterback runs by week for Cam Newton 2020",
    subtitle = "",
    caption = "Data: @espnscrapeR | Plot: @LauraStickells"
  ) +
  scale_x_continuous(breaks = seq(min(pbp$week), max(pbp$week), by = 1)) +
  scale_y_continuous(labels = label_percent(accuracy = 1))
## Warning: Ignoring unknown aesthetics: text
ggplotly(graph, tooltip = ("text"))

Correlation between Newton’s QBR and run percentage.

pbp_name_fix <- pbp
### Don't run the lines below twice
pbp_name_fix$passer <- trimws(gsub(".", ". ", pbp_name_fix$passer, fixed = TRUE))
pbp_name_fix$rusher <- trimws(gsub(".", ". ", pbp_name_fix$rusher, fixed = TRUE))

all_qbs <- pbp_name_fix %>%
    filter(passer != 'NA', cp!= 'NA', season == 2020) %>%
    group_by(passer, passer_id) %>%
    summarise(
        plays = n()
    ) %>%
    filter(plays >= 200) %>%
    select(passer) %>%
    arrange(passer) 
## `summarise()` regrouping output by 'passer' (override with `.groups` argument)
all_qbs <- all_qbs[['passer']]

pcts <- pbp_name_fix %>%
  filter(epa != 0, passer %in% all_qbs | rusher %in% all_qbs, play_type != "qb_kneel") %>%
  select(posteam, desc, play_type, qb_scramble, pass, rush, season, week, passer, rusher) %>%
  mutate(
    player = case_when(
      !is.na(passer) ~ passer,
      !is.na(rusher) ~ rusher
    ) 
  ) %>%
  group_by(player, season, week) %>%
  summarise(
    run_pct = sum(rush)/n(),
    runs = sum(rush),
    pass_pct = sum(pass)/n(),
    passes = sum(pass)
  )
## `summarise()` regrouping output by 'player', 'season' (override with `.groups` argument)
qbrs <- qbr_by_game %>%
  filter(short_name %in% all_qbs)

table <- left_join(qbrs, pcts, by = c("short_name" = "player", "season" = "season", "game_week" = "week")) %>%
  group_by("short_name") %>%
  mutate(
    n = n()
  ) %>%
  filter(n >= 10) %>%
  ungroup()

table %>%
  filter(short_name %in% c('C. Newton')) %>%
  ggplot(aes(x = run_pct, y = qbr_total, color = short_name)) +
  stat_smooth(method = "lm", geom = "line", alpha = 0.5, se = FALSE, size = 1) +
  geom_point(alpha=.7) +
  theme_fivethirtyeight() +
  theme(
    legend.title = element_blank(),
    strip.text = element_text(face = "bold"),
    axis.title.y = element_text(),
    axis.title.x = element_text()
    ) +
  labs(
    y = "Total QBR",
    x = "Run Percentage",
    title = "Total QBR compared to QB run percentage\nby game for Cam Newton",
    subtitle = "The two variable's show a positive correlation",
    caption = "Data: @espnscrapeR and @nflfastR | Plot: @LauraStickells"
  ) +
  scale_x_continuous(breaks = seq(min(table$runs), max(table$runs), by = .05), labels = label_percent(accuracy = 1))
## `geom_smooth()` using formula 'y ~ x'

Correlation table for all the leagues QBs.

cor_p_table <- data.frame(matrix(ncol=3, nrow=0, dimnames=list(NULL, c("QB", "Cor", "pvalue"))))

for (i in all_qbs) {
  temp_table <- data.frame()
  temp_table <- table %>%
    filter(short_name == i)
  res <- cor.test(temp_table$run_pct, temp_table$qbr_total)
  new_row <- c(i, round(res$estimate, 2), round(res$p.value, 3))
  cor_p_table[nrow(cor_p_table) + 1, ] <- new_row 
}

cor_p_table <- transform(cor_p_table, Cor = as.numeric(Cor))
cor_p_table <- transform(cor_p_table, pvalue = as.numeric(pvalue))

cor_p_table %>%
  arrange(desc(Cor)) %>%
  gt() %>%
  tab_header(
    title = "Correlation Between QBR and QB Run %",
    subtitle = "Significant correlations are highlighted"
  ) %>% 
  tab_options(
    table.border.top.color = "white",
    row.striping.include_table_body = FALSE
  ) %>%
  tab_source_note(
    source_note = "SOURCE: @nflfastR and @espnscrapR"
  ) %>%
  cols_label(
    QB = "PLAYER",
    Cor = "CORRELATION",
    pvalue = "P-VALUE"
  ) %>%
  tab_style(
    style = list(
      cell_fill(color = "lightyellow")
      ),
    locations = cells_body(
      columns = vars(QB, Cor, pvalue),
      rows = pvalue < .07)
  ) %>%
  tab_style(
    style = list(
      cell_text(weight = "bold")
      ),
    locations = cells_body(
      columns = vars(QB, Cor, pvalue),
      rows = QB == 'C. Newton')
  )
Correlation Between QBR and QB Run %
Significant correlations are highlighted
PLAYER CORRELATION P-VALUE
K. Murray 0.56 0.002
D. Jones 0.52 0.009
N. Mullens 0.43 0.097
J. Herbert 0.35 0.263
N. Foles 0.35 0.009
S. Darnold 0.20 0.247
J. Goff 0.19 0.134
M. Ryan 0.19 0.007
D. Prescott 0.18 0.146
K. Cousins 0.18 0.071
C. Newton 0.16 0.069
G. Minshew II 0.14 0.521
D. Carr 0.13 0.140
A. Rodgers 0.11 0.133
J. Burrow 0.10 0.788
R. Wilson 0.09 0.312
D. Watson 0.08 0.576
R. Tannehill 0.06 0.514
A. Smith 0.05 0.518
B. Roethlisberger 0.04 0.594
T. Bridgewater 0.04 0.770
D. Brees 0.02 0.725
P. Rivers 0.02 0.764
P. Mahomes 0.00 0.983
T. Brady 0.00 0.973
B. Mayfield -0.02 0.906
M. Stafford -0.03 0.739
R. Fitzpatrick -0.05 0.584
A. Dalton -0.06 0.509
C. Wentz -0.13 0.296
J. Allen -0.15 0.341
L. Jackson -0.33 0.060
D. Lock -0.39 0.170
SOURCE: @nflfastR and @espnscrapR

Quarterback run percentage for all QBs in 2020 with three or more games.

run_pct_2020 <- table %>%
  filter(short_name %in% all_qbs, season == 2020) %>%
  group_by(short_name, headshot_href, team) %>%
  summarise(
    run_pct = sum(runs)/(sum(passes)+sum(runs)),
    runs = sum(runs),
    games = n()
  ) %>%
  filter(games >= 3) %>%
  arrange(desc(run_pct))
## `summarise()` regrouping output by 'short_name', 'headshot_href' (override with `.groups` argument)
asp_ratio <- 1.618

run_pct_graph <- run_pct_2020 %>%
  left_join(teams_colors_logos, by = c("team" = "team_abbr")) %>%
  ggplot(aes(x = reorder(short_name, -run_pct) , y = run_pct)) +
  geom_col(aes(fill = team_color, color = team_color), alpha = 0.7) +
  geom_image(aes(image = headshot_href), size = 0.075, by = "width", asp = asp_ratio) +
  scale_color_identity(aesthetics = c("color", "fill")) +
  ggthemes::theme_fivethirtyeight() +
  theme(
    legend.position = "bottom",
    legend.title = element_blank(),
    strip.text = element_text(face = "bold"),
    axis.title.y = element_text(),
    axis.title.x = element_blank(),
    axis.text.x = element_text(angle = 90)
    ) +
  labs(
    y = "Run Percentage",
    title = "Quarterback Run Percentage in 2020",
    subtitle = "For quarterbacks with three or more games",
    caption = "Data: @nflfastR | Plot: @LauraStickells"
  ) 

run_pct_graph

Used this to calculate a QB’s percent of total rushing attempts out of a team’s total rushes. Also used this to compare rushing vs. passing success. Found lots of interesting stuff, but the post was getting long so I stopped here. Could look further into this in the future.

pbp %>%
  filter(season == 2020, epa != 0, posteam == "BAL", epa != 0, rush == 1) %>%
  select(desc, down, week, yardline_100, success, epa, pass, rush, rusher, success) %>%
  mutate(
    count = n()
  ) %>%
  group_by(rusher) %>%
  summarise(
    rushes = n(),
    rush_pct = n()/count,
    success = sum(success)/n()
  ) %>%
  unique() %>%
  arrange(desc(rushes))
## `summarise()` regrouping output by 'rusher' (override with `.groups` argument)
## # A tibble: 11 x 4
## # Groups:   rusher [11]
##    rusher        rushes rush_pct success
##    <chr>          <int>    <dbl>   <dbl>
##  1 G.Edwards        109  0.287     0.459
##  2 J.Dobbins        101  0.266     0.376
##  3 L.Jackson         80  0.211     0.475
##  4 M.Ingram          63  0.166     0.413
##  5 J.Hill            10  0.0263    0.2  
##  6 R.Griffin III      8  0.0211    0.625
##  7 T.McSorley         4  0.0105    0.25 
##  8 D.Duvernay         2  0.00526   0.5  
##  9 M.Brown            1  0.00263   0    
## 10 M.Skura            1  0.00263   0    
## 11 P.Ricard           1  0.00263   0
pbp %>%
  filter(season == 2020, epa != 0, rusher == 'L.Jackson' | passer == 'L.Jackson', down <= 4) %>%
  select(desc, down, week, yardline_100, success, epa, pass, rush) %>%
  filter(rush == 1) %>%
  summarise(
    rush_success = sum(success)/n(),
    count = n()
  )
## # A tibble: 1 x 2
##   rush_success count
##          <dbl> <int>
## 1        0.475    80
pbp %>%
  filter(season == 2020, epa != 0, rusher == 'L.Jackson' | passer == 'L.Jackson', down <= 4) %>%
  select(desc, down, week, yardline_100, success, epa, pass, rush) %>%
  filter(pass == 1) %>%
  summarise(
    pass_success = sum(success)/n(),
    count = n()
  )
## # A tibble: 1 x 2
##   pass_success count
##          <dbl> <int>
## 1        0.462   394